import allure
import logging

import pytest

from utils.send_request import send_jdbc_request
from utils.get_keywords import GetKeywords
from utils.base_asserts import BaseAsserts,MainAsserts
from abc import ABC, abstractmethod

class DataAsserts(ABC):
    @abstractmethod
    def http_assert(self, case, res):
        pass


class SingleAssert(DataAsserts):

    @allure.step("3. HTTP响应断言")
    def http_assert(self, case, res):
        if case["check"]:

            result = GetKeywords.get_keyword(res, case["check"])
            # result = jsonpath.jsonpath(res.json(), case["check"])[0]

            logging.info(f"3. HTTP响应断言内容: 实际结果({result}) == 预期结果({case["expected"]})")
            assert result == case["expected"]
        else:

            logging.info(f"3. HTTP响应断言内容: 预期结果({case["expected"]}) in 实际结果({res.text})")
            # assert case["expected"] in res.text
            assert case["expected"] in str(res)


class MultipleAssert(DataAsserts):
    @allure.step("3. HTTP多重响应断言")
    def http_assert(self, case, res):
        if case["check"]:
            MainAsserts(case, res).main_assert()

            # for key, value in eval(case["check"]).items():
            #     result = GetKeywords.get_keyword(res, key)
            #     logging.info(f"3. HTTP多重响应断言内容: 预期结果({value}) in 实际结果({result})")
            #     pytest.assume(result == value)

def obj_process(case):
    """
    对象的处理，根据传入的case不同，返回不同的对象
    :return:
    """
    try:
        eval(case["check"])
    except:
        return SingleAssert()
    else:
        return MultipleAssert()


def http_assert(case, res):
    """
    真正的调用逻辑，无论怎么新增http返回值的断言，都是调用这个函数
    :param case:测试用例
    :param res:返回结果
    :return:
    """
    obj_process(case).http_assert(case, res)


class BaseJdbcAsserts(ABC):
    @abstractmethod
    def jdbc_assert(self, case):
        pass

class SingleJdbcAsserts(BaseJdbcAsserts):
    def jdbc_assert(self, case):
        if case["sql_check"] and case["sql_expected"]:
            with allure.step("3. JDBC响应断言"):
                result = send_jdbc_request(case["sql_check"])
                # logging.info(f"3. JDBC响应断言内容: 实际结果({result}) == 预期结果({case["sql_expected"]})")
                logging.info(f"3. JDBC响应断言内容: 预期结果({case["sql_expected"]}) in 实际结果({result})")
                assert case["sql_expected"] in str(result)


class MultipleJdbcAsserts(BaseJdbcAsserts):
    """
    多重数据库断言
    """
    def jdbc_assert(self, case):
        if case["sql_check"] and case["sql_expected"]:
            with allure.step("3. JDBC多重响应断言"):
                sql_check = eval(case["sql_check"])
                sql_expected = eval(case["sql_expected"])
                for sql, expected in zip(sql_check, sql_expected):
                    result = send_jdbc_request(sql)
                    logging.info(f"3. JDBC多重响应断言内容: 预期结果({expected}) in 实际结果({result})")
                    pytest.assume(expected in str(result))


def obj_jdbc_process(case):
    """
    对象的处理，根据传入的case不同，返回不同的对象
    :return:
    """
    try:
        eval(case["sql_check"])
    except:
        return SingleJdbcAsserts()
    else:
        return MultipleJdbcAsserts()


def jdbc_assert(case):
    """
    真正的调用逻辑，无论怎么新增http返回值的断言，都是调用这个函数
    :param case:测试用例
    :return:
    """
    obj_jdbc_process(case).jdbc_assert(case)




